home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
9-Digit Zip Code Directory
/
9-Digit Zip Code Directory (American Business Information) (ABIZIP-12).ISO
/
z4src.zip
/
Z4CSCP.C
< prev
next >
Wrap
C/C++ Source or Header
|
1995-08-17
|
17KB
|
509 lines
//----------------------------------------------------------------------------
// MODULE DESCRIPTION
//
// Module: z4cscp.c
// Title: ZIP+4 Engine
// Notice: John M. Weeder
// Copyright (c) 1993. All rights reserved.
// This module contains proprietary information and should be
// treated as confidential.
//
//----------------------------------------------------------------------------
// MAINTENANCE HISTORY
//
// $Workfile$
// $Revision$
// $Author$
// $Date$
// $Log$
//
//----------------------------------------------------------------------------
// MODULE NARRATIVE
//
//
// This module contains the compressor for the city/state file.
//
// The code in this module should be written entirely in C.
// Do not use any C++ constructs.
//
// This module is portable to:
// DOS 3.X+
// MS Windows 3.X+
// OS/2 2.X+
// OS/2 2.0 PM
// SCO UNIX.
//
// The following compilers are supported:
// MSC 6.0A
// MSC/C++ 7.0
// Borland C++ 3.1 for DOS
// Borland C++ 1.0 for OS/2 2.X
// SCO UNIX cc
//
//----------------------------------------------------------------------------
#include <z4.h>
//----------------------------------------------------------------------------
// Globals
//----------------------------------------------------------------------------
typedef struct _G
{
PVOID pcache; // Word/string cache
BOOL fError; // Error while compressing?
Z4_CS ctystPrev; // Previous city/state record
Z4_CS ctystCur; // Current city/state record
Z4_CS ctyst; // City/state being processed
BOOL fPending; // Record pending?
SIZET cZip;
SIZET cRecType;
SIZET cPof;
SIZET cLL;
SIZET cState;
SIZET cCity;
SIZET cCityAbbrev;
SIZET cLLName;
SIZET cCountyNo;
SIZET cCountyName;
SIZET cFacility;
PZ4_PF_TBL ppf_tbl;
} G;
static G g;
//----------------------------------------------------------------------------
// Prototypes
//----------------------------------------------------------------------------
static BOOL FN_L Z4CSCompressAppend(PBYTE, SIZET, PSIZET);
static BOOL FN_L Z4CSCompressEqual(PZ4_CS, PZ4_CS);
static BOOL FN_L Z4CSCompressInitialize(void);
static BOOL FN_L Z4CSCompressReset(void);
static BOOL FN_L Z4CSCompressTerminate(void);
static SHORT FN_L Z4CSCompressValidate(PPSZ);
//----------------------------------------------------------------------------
// Description: Compression function
// Parameters: pdatacomp Compressor data
// Returns: Compression function result code. See data.h.
//----------------------------------------------------------------------------
SHORT FN_E Z4CSCompress(PDATACOMP pdatacomp)
{
LONG lRec = pdatacomp->dlmrec.lId;
PPSZ ppsz = pdatacomp->dlmrec.apsz;
SHORT sResult;
switch (lRec)
{
case DAI_INITIALIZE: // Initialize at startup
{
PDATACFG pcfg = pdatacomp->dlmrec.pcfg;
if (!Z4CSCompressInitialize()
|| !Z4PofCreate(&g.ppf_tbl, Z4_PF_TBL_DISCARD_MAX)
|| !Z4PofRead(g.ppf_tbl, Z4_PF_TBL_DISCARD))
return DAO_FAILURE;
g.cZip = DataField(pcfg, "zipcode");
g.cRecType = DataField(pcfg, "record_type_code");
g.cCity = DataField(pcfg, "city_name");
g.cCityAbbrev = DataField(pcfg, "city_abbrev");
g.cFacility = DataField(pcfg, "facility");
g.cLL = DataField(pcfg, "last_line");
g.cLLName = DataField(pcfg, "last_line_name");
g.cPof = DataField(pcfg, "finance");
g.cState = DataField(pcfg, "state_abbrev");
g.cCountyNo = DataField(pcfg, "county_no");
g.cCountyName = DataField(pcfg, "county_name");
return DAO_SUCCESS;
}
case DAI_TERMINATE: // Terminate
case DAI_FAILURE:
Z4CSCompressTerminate();
return DAO_SUCCESS;
case DAI_START_BLK: // Start block
Z4CSCompressReset();
return DAO_SUCCESS;
case DAI_END_BLK: // End block
return DAO_SUCCESS;
case DAI_LAST_REC: // Last record pending, append and flush
if (g.fError)
return DAO_FAILURE;
Z4CSCompressAppend(pdatacomp->pb, pdatacomp->cbMax, &pdatacomp->cb);
return DAO_FLUSH;
}
sResult = Z4CSCompressValidate(ppsz);
if (sResult == (SHORT)g.cState || Z4PofFind(g.ppf_tbl, ppsz[g.cPof]) >= 0L) // Invalid state, or invalid POF -- discard record
return DAO_SKIP;
if (sResult >= 0) {
Output("\n*** Field %d has invalid value in record %ld.\n '%s'='%s'\n",
sResult, lRec,
pdatacomp->dlmrec.pcfg->afld[sResult].szName,
ppsz[sResult]);
g.fError = TRUE;
}
if (g.fError) // If an error occurred, just keep
return DAO_SUCCESS; // scanning for invalid recods
printf("%ld",lRec);
Assert(g.ctyst.state >= g.ctystCur.state);
if (g.fPending)
{
if (g.ctyst.state == g.ctystCur.state
&& strcmp(g.ctyst.szCity, g.ctystCur.szCity) == 0)
{
if (!Z4CSCompressEqual(&g.ctyst, &g.ctystCur))
{
Z4CSCompressAppend(pdatacomp->pb, pdatacomp->cbMax, &pdatacomp->cb);
return DAO_MARK_FLUSH;
}
strcpy(g.ctystCur.szZip5Hi, g.ctyst.szZip5Lo);
return DAO_NEXT;
}
else
{
Z4CSCompressAppend(pdatacomp->pb, pdatacomp->cbMax, &pdatacomp->cb);
return DAO_MARK_FLUSH;
}
}
g.ctystCur = g.ctyst;
g.fPending = TRUE;
return DAO_NEXT;
}
//----------------------------------------------------------------------------
// Description: Append a compressed record to the output buffer.
// Parameters: pctyst City/state record to append
// pb Buffer for compressed data.
// cb Size of buffer.
// pcb Pointer to variable containing current size of
// compressed data. Updated on return to contain
// size of compressed data after this record is
// processed.
// Returns: TRUE if successful.
//----------------------------------------------------------------------------
static BOOL FN_L Z4CSCompressAppend(PBYTE pb, SIZET cb, PSIZET pcb)
{
BYTE b1 = 0, b2 = 0;
PBYTE pbStart = pb;
SIZET cString;
//
// Create bit flags indicating which data is being written
//
NOTUSED(cb);
if (strcmp(g.ctystPrev.szZip5Hi, g.ctystCur.szZip5Hi) != 0)
b1 |= CS1_ZIP5_HI;
if (strcmp(g.ctystPrev.szZip5Lo, g.ctystCur.szZip5Lo) != 0)
b1 |= CS1_ZIP5_LO;
if (strcmp(g.ctystPrev.szCity, g.ctystCur.szCity) != 0)
b1 |= CS1_CITY;
if (strcmp(g.ctystPrev.szCityAbbrev, g.ctystCur.szCityAbbrev) != 0)
b1 |= CS1_CITY_ABBREV;
if (g.ctystPrev.facility != g.ctystCur.facility)
b1 |= CS1_FACILITY;
if (g.ctystPrev.state != g.ctystCur.state)
b1 |= CS1_STATE;
if (g.ctystPrev.rectype != g.ctystCur.rectype)
b1 |= CS2_REC_TYPE;
if (strcmp(g.ctystPrev.szFinance, g.ctystCur.szFinance) != 0)
b2 |= CS2_FINANCE;
if (strcmp(g.ctystPrev.szLastLine, g.ctystCur.szLastLine) != 0)
b2 |= CS2_LAST_LINE;
if (strcmp(g.ctystPrev.szLastLineName, g.ctystCur.szLastLineName) != 0)
b2 |= CS2_LAST_LINE_NAME;
if (strcmp(g.ctystPrev.szCountyNo, g.ctystCur.szCountyNo) != 0)
b2 |= CS2_COUNTY_NO;
if (strcmp(g.ctystPrev.szCounty, g.ctystCur.szCounty) != 0)
b2 |= CS2_COUNTY;
//
// If last line and finance number are changing and the last line
// and finance are the same, set a special bit flag.
//
if ((b2 & CS2_FINANCE)
&& (b2 & CS2_LAST_LINE)
&& strcmp(g.ctystCur.szFinance, g.ctystCur.szLastLine) == 0)
{
b2 &= ~CS2_LAST_LINE;
b2 |= CS2_LL_IS_POF;
}
//
// If last line name and city name are changing and they
// are the same, set a special bit flag.
//
if ((b1 & CS1_CITY)
&& (b2 & CS2_LAST_LINE_NAME)
&& strcmp(g.ctystCur.szCity, g.ctystCur.szLastLineName) == 0)
{
b2 &= ~CS2_LAST_LINE_NAME;
b2 |= CS2_LL_IS_CITY;
}
//
// If ZIP 5 hi range is changing to blank, set bit flag.
//
if ((b1 & CS1_ZIP5_HI)
&& !g.ctystCur.szZip5Hi[0])
{
b1 &= ~CS1_ZIP5_HI;
b2 |= CS1_NO_ZIP5_HI;
}
if (b2)
b1 |= CS_BYTE_FOLLOWS;
//
// Write compressed data
//
Assert(b1);
*pb++ = b1; // Write bit flags
if (b2)
*pb++ = b2;
if (b1 & CS1_ZIP5_HI)
{
stra2b(pb, MAX_ZIP5_BCD, g.ctystCur.szZip5Hi, MAX_ZIP5);
pb += MAX_ZIP5_BCD;
}
if (b1 & CS1_ZIP5_LO)
{
stra2b(pb, MAX_ZIP5_BCD, g.ctystCur.szZip5Lo, MAX_ZIP5);
pb += MAX_ZIP5_BCD;
}
if (b1 & CS1_CITY)
{
StringEncode(g.pcache, pb, &cString, g.ctystCur.szCity);
pb += cString;
}
if (b1 & CS1_CITY_ABBREV)
{
StringEncode(g.pcache, pb, &cString, g.ctystCur.szCityAbbrev);
pb += cString;
}
if (b1 & CS1_STATE)
*pb++ = (BYTE)g.ctystCur.state;
if (b1 & CS1_FACILITY)
*pb++ = (BYTE)g.ctystCur.facility;
if (b1 & CS2_REC_TYPE)
*pb++ = (BYTE)g.ctystCur.rectype;
if (b2 & CS2_FINANCE)
{
stra2b(pb, MAX_FINANCE_BCD, g.ctystCur.szFinance, MAX_FINANCE);
pb += MAX_FINANCE_BCD;
}
if (b2 & CS2_LAST_LINE)
{
stra2b(pb, MAX_LAST_LINE_BCD, g.ctystCur.szLastLine, MAX_LAST_LINE);
pb += MAX_LAST_LINE_BCD;
}
if (b2 & CS2_LAST_LINE_NAME)
{
StringEncode(g.pcache, pb, &cString, g.ctystCur.szLastLineName);
pb += cString;
}
if (b2 & CS2_COUNTY_NO)
{
stra2b(pb, MAX_COUNTY_NO_BCD, g.ctystCur.szCountyNo, MAX_COUNTY_NO);
pb += MAX_COUNTY_NO_BCD;
}
if (b2 & CS2_COUNTY)
{
StringEncode(g.pcache, pb, &cString, g.ctystCur.szCounty);
pb += cString;
}
//
// Clean up
//
*pcb = (SIZET)(pb - pbStart); // Return number of bytes written
g.ctystPrev = g.ctystCur; // Store record which was written and
g.fPending = FALSE; // update flags
return TRUE;
}
//----------------------------------------------------------------------------
// Description: Compare two city/state records except for ZIP range
// Parameters: pctyst1 Records to compare
// pctyst2
// Returns: TRUE if equal.
//----------------------------------------------------------------------------
static BOOL FN_L Z4CSCompressEqual(PZ4_CS pctyst1, PZ4_CS pctyst2)
{
return pctyst1->facility == pctyst2->facility
&& pctyst1->rectype == pctyst2->rectype
&& pctyst1->state == pctyst2->state
&& strcmp(pctyst1->szCity,pctyst2->szCity) == 0
&& strcmp(pctyst1->szCityAbbrev,pctyst2->szCityAbbrev) == 0
&& strcmp(pctyst1->szFinance,pctyst2->szFinance) == 0
&& strcmp(pctyst1->szLastLine,pctyst2->szLastLine) == 0
&& strcmp(pctyst1->szLastLineName,pctyst2->szLastLineName) == 0
&& strcmp(pctyst1->szCountyNo,pctyst2->szCountyNo) == 0
&& strcmp(pctyst1->szCounty,pctyst2->szCounty) == 0;
}
//----------------------------------------------------------------------------
// Description: Initialize city/state record compressor
// Parameters:
// Returns: TRUE if successful.
//----------------------------------------------------------------------------
static BOOL FN_L Z4CSCompressInitialize(void)
{
memset(&g, 0, sizeof(g));
g.pcache = StringCreate(Z4_CS_WORD_CACHE, CP_WORD_VERIFY);
if (g.pcache == NULL)
return FALSE;
return Z4CSCompressReset();
}
//----------------------------------------------------------------------------
// Description: Reset record compressor to compress another block
// Parameters:
// Returns: TRUE if successful.
//----------------------------------------------------------------------------
static BOOL FN_L Z4CSCompressReset(void)
{
StringReset(g.pcache); // Reset string cache
// Clear pending records
memset(&g.ctyst, 0, sizeof(g.ctyst));
memset(&g.ctystPrev, 0, sizeof(g.ctystPrev)); // Set default record characteristics
g.ctystPrev.facility = Z4_FACILITY_PO;
g.ctystPrev.rectype = Z4_CS_TYPE_NON_UNIQUE;
g.ctystPrev.state = Z4_ST_FIRST;
g.fPending = FALSE; // Reset flags
return TRUE;
}
//----------------------------------------------------------------------------
// Description: Terminate record compressor
// Parameters:
// Returns: TRUE if successful.
//----------------------------------------------------------------------------
static BOOL FN_L Z4CSCompressTerminate(void)
{
if (g.pcache) // Close word cache
StringDestroy(g.pcache);
Z4PofDestroy(g.ppf_tbl);
memset(&g, 0, sizeof(g));
return TRUE;
}
//----------------------------------------------------------------------------
// Description: Check if all characters in a string are numeric or if
// the second character is an A.
// Parameters: pcsz String
// Returns: TRUE if all characters are numeric
//----------------------------------------------------------------------------
BOOL FN_E strisnumeric2(PCSZ pcsz)
{
return strisvalid(pcsz, "[aAbBcC0-9]*");
}
//----------------------------------------------------------------------------
// Description: Validate city/state data and copy to fields.
// Parameters: ppsz Record data
// Returns: -1 if successful. Field id of invalid field
//----------------------------------------------------------------------------
static SHORT FN_L Z4CSCompressValidate(PPSZ ppsz)
{
memset(&g.ctyst, 0, sizeof(g.ctyst));
// Check valid zip code
if (!strisnumeric(ppsz[g.cZip]) || strlen(ppsz[g.cZip]) != MAX_ZIP5)
return (SHORT)g.cZip;
strcpy(g.ctyst.szZip5Lo, ppsz[g.cZip]);
g.ctyst.rectype = Z4FindCSRecordType(ppsz[g.cRecType]); // Check record type
if (g.ctyst.rectype == Z4_CS_TYPE_INVALID)
return (SHORT)g.cRecType;
if (!strisnumeric(ppsz[g.cPof]) // Finance number
|| strlen(ppsz[g.cPof]) != MAX_FINANCE)
return (SHORT)g.cPof;
strcpy(g.ctyst.szFinance, ppsz[g.cPof]);
// Last line number may start with the letters B,C,N,V,W,X,Y,Z
// or a digit. It must be 6 characters in length.
// The characters N thru Z are converted to A thru F so that it can
// be encoded in bcd.
// an error is in the data file for Texarkana Ar. W2ZZZZ is an invalid
// Last Line entry, so am converting it to W2AAAA.
if (ppsz[g.cLL][2]) {
if (!(isdigit(ppsz[g.cLL][2]) && (ppsz[g.cLL][2]) == 'Z')
|| !isdigit(ppsz[g.cLL][3] && (ppsz[g.cLL][3]) == 'Z')
|| !isdigit(ppsz[g.cLL][4] && (ppsz[g.cLL][4]) == 'Z')
|| !isdigit(ppsz[g.cLL][5] && (ppsz[g.cLL][5]) == 'Z')) {
ppsz[g.cLL][2] = 'A';
ppsz[g.cLL][3] = 'A';
ppsz[g.cLL][4] = 'A';
ppsz[g.cLL][5] = 'A';
}
}
if (ppsz[g.cLL][0]) // If a last line number is present
{ // copy it
if (!(isdigit(ppsz[g.cLL][0])
|| ppsz[g.cLL][0] == 'B'
|| ppsz[g.cLL][0] == 'C'
|| ppsz[g.cLL][0] == 'N'
|| ppsz[g.cLL][0] == 'V'
|| ppsz[g.cLL][0] == 'W'
|| ppsz[g.cLL][0] == 'X'
|| ppsz[g.cLL][0] == 'Y'
|| ppsz[g.cLL][0] == 'Z')
|| !strisnumeric2(ppsz[g.cLL] + 1)
// use the above test to see if we can get A to work
// || !strisnumeric(ppsz[g.cLL] + 1) //original code
|| strlen(ppsz[g.cLL]) != MAX_LAST_LINE)
return (SHORT)g.cLL; // invalid last line
strcpy(g.ctyst.szLastLine, ppsz[g.cLL]);
if (g.ctyst.szLastLine[0] == 'N')
g.ctyst.szLastLine[0] = 'A';
if (g.ctyst.szLastLine[0] == 'V')
g.ctyst.szLastLine[0] = 'B';
if (g.ctyst.szLastLine[0] == 'W')
g.ctyst.szLastLine[0] = 'C';
if (g.ctyst.szLastLine[0] == 'X')
g.ctyst.szLastLine[0] = 'D';
if (g.ctyst.szLastLine[0] == 'Y')
g.ctyst.szLastLine[0] = 'E';
if (g.ctyst.szLastLine[0] == 'Z')
g.ctyst.szLastLine[0] = 'F';
}
else // Else, use finance number
strcpy(g.ctyst.szLastLine, g.ctyst.szFinance);
// Check state code
g.ctyst.state = Z4FindState(ppsz[g.cState]);
if (g.ctyst.state == Z4_ST_INVALID) // Invalid state code
return (SHORT)g.cState;
strcpy(g.ctyst.szCity, Z4Clean(ppsz[g.cCity]));
strcpy(g.ctyst.szCityAbbrev, Z4Clean(ppsz[g.cCityAbbrev]));
strcpy(g.ctyst.szLastLineName, Z4Clean(ppsz[g.cLLName]));
if (ppsz[g.cCountyNo][0])
{ // Check county number
if (!strisnumeric(ppsz[g.cCountyNo])
|| strlen(ppsz[g.cCountyNo]) != MAX_COUNTY_NO)
return (SHORT)g.cCountyNo;
strcpy(g.ctyst.szCountyNo, ppsz[g.cCountyNo]);
strcpy(g.ctyst.szCounty, ppsz[g.cCountyName]);
}
else
strcpy(g.ctyst.szCountyNo, "000");
// Facility code
g.ctyst.facility = Z4FindFacility(ppsz[g.cFacility]);
if (g.ctyst.facility == Z4_FACILITY_INVALID)
return (SHORT)g.cFacility;
return -1;
}
//----------------------------------------------------------------------------
//------------------------------- End of File --------------------------------
//----------------------------------------------------------------------------